home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / script-fu / script-fu.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-14  |  29.8 KB  |  1,152 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #if HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27.  
  28. #include <gtk/gtk.h>
  29. #include <libgimp/gimp.h>
  30.  
  31. #include "siod.h"
  32. #include "script-fu-console.h"
  33. #include "script-fu-constants.h"
  34. #include "script-fu-scripts.h"
  35. #include "script-fu-server.h"
  36.  
  37. #include "script-fu-intl.h"
  38.  
  39. extern FILE *siod_output;
  40.  
  41. /* External functions
  42.  */
  43. extern void  gimp_extension_process (guint timeout);
  44. extern void  gimp_extension_ack     (void);
  45.  
  46. extern void  init_subrs   (void);
  47. extern void  init_trace   (void);
  48. extern void  init_regex   (void);
  49.  
  50. extern long  nlength      (LISP   obj);
  51. extern LISP  leval_define (LISP   args,
  52.                LISP   env);
  53.  
  54. extern void  fput_st      (FILE  *f,
  55.                gchar *st);
  56.  
  57. /* Declare local functions.
  58.  */
  59. static void  sfquit (void);
  60. static void  query  (void);
  61. static void  run    (gchar        *name,
  62.              gint          nparams,
  63.              GimpParam    *param,
  64.              gint         *nreturn_vals,
  65.              GimpParam   **return_vals);
  66.  
  67. static gint  init_interp              (void);
  68. static void  init_gimp                (void);
  69. static void  init_procedures          (void);
  70. static void  init_constants           (void);
  71. static void  convert_string           (gchar *str);
  72.  
  73. static gint  sputs_fcn                (gchar *st,
  74.                        void  *dest);
  75. static LISP  lprin1s                  (LISP   exp,
  76.                        gchar *dest);
  77.  
  78. static LISP  marshall_proc_db_call    (LISP a);
  79. static LISP  script_fu_register_call  (LISP a);
  80. static LISP  script_fu_quit_call      (LISP a);
  81.  
  82. static void  script_fu_auxillary_init (void);
  83. static void  script_fu_refresh_proc   (gchar      *name,
  84.                        gint        nparams,
  85.                        GimpParam  *params,
  86.                        gint       *nreturn_vals,
  87.                        GimpParam **return_vals);
  88.  
  89.  
  90. GimpPlugInInfo PLUG_IN_INFO =
  91. {
  92.   NULL,   /* init_proc  */
  93.   sfquit, /* quit_proc  */
  94.   query,  /* query_proc */
  95.   run,    /* run_proc   */
  96. };
  97.  
  98. static gchar *siod_argv[] =
  99. {
  100.   "siod",
  101.   "-h100000:10",
  102.   "-g0",
  103.   "-o1000",
  104.   "-s200000",
  105.   "-n2048",
  106.   "-v0",
  107. };
  108.  
  109. static gint script_fu_base = TRUE;
  110. extern gint server_mode;
  111.  
  112. gint script_fu_done = FALSE;  /*  declared extern in script-fu-server.c  */
  113.  
  114.  
  115. MAIN ()
  116.  
  117. static void
  118. sfquit (void)
  119. {
  120. }
  121.  
  122. static void
  123. query (void)
  124. {
  125.   static GimpParamDef console_args[] =
  126.   {
  127.     { GIMP_PDB_INT32,  "run_mode", "Interactive, [non-interactive]" }
  128.   };
  129.   static gint nconsole_args = sizeof (console_args) / sizeof (console_args[0]);
  130.  
  131.   static GimpParamDef eval_args[] =
  132.   {
  133.     { GIMP_PDB_INT32,  "run_mode", "[Interactive], non-interactive" },
  134.     { GIMP_PDB_STRING, "code",     "The code to evaluate" }
  135.   };
  136.   static gint neval_args = sizeof (eval_args) / sizeof (eval_args[0]);
  137.  
  138.   static GimpParamDef server_args[] =
  139.   {
  140.     { GIMP_PDB_INT32,  "run_mode", "[Interactive], non-interactive" },
  141.     { GIMP_PDB_INT32,  "port",     "The port on which to listen for requests" },
  142.     { GIMP_PDB_STRING, "logfile",  "The file to log server activity to" }
  143.   };
  144.   static gint nserver_args = sizeof (server_args) / sizeof (server_args[0]);
  145.  
  146.   gimp_plugin_domain_register ("gimp-script-fu", NULL);
  147.  
  148.   gimp_install_procedure ("extension_script_fu",
  149.               "A scheme interpreter for scripting GIMP operations",
  150.               "More help here later",
  151.               "Spencer Kimball & Peter Mattis",
  152.               "Spencer Kimball & Peter Mattis",
  153.               "1997",
  154.               NULL,
  155.               NULL,
  156.               GIMP_EXTENSION,
  157.               0, 0, NULL, NULL);
  158.  
  159.   gimp_install_procedure ("extension_script_fu_console",
  160.               "Provides a console mode for script-fu development",
  161.               "Provides an interface which allows interactive scheme development.",
  162.               "Spencer Kimball & Peter Mattis",
  163.               "Spencer Kimball & Peter Mattis",
  164.               "1997",
  165.               N_("<Toolbox>/Xtns/Script-Fu/Console..."),
  166.               NULL,
  167.               GIMP_EXTENSION,
  168.               nconsole_args, 0,
  169.               console_args, NULL);
  170.  
  171. #ifndef G_OS_WIN32
  172.   gimp_install_procedure ("extension_script_fu_server",
  173.               "Provides a server for remote script-fu operation",
  174.               "Provides a server for remote script-fu operation",
  175.               "Spencer Kimball & Peter Mattis",
  176.               "Spencer Kimball & Peter Mattis",
  177.               "1997",
  178.               N_("<Toolbox>/Xtns/Script-Fu/Server..."),
  179.               NULL,
  180.               GIMP_EXTENSION,
  181.               nserver_args, 0,
  182.               server_args, NULL);
  183. #endif
  184.  
  185.   gimp_install_procedure ("extension_script_fu_eval",
  186.               "Evaluate scheme code",
  187.               "Evaluate the code under the scheme interpeter (primarily for batch mode)",
  188.               "Manish Singh",
  189.               "Manish Singh",
  190.               "1998",
  191.               NULL,
  192.               NULL,
  193.               GIMP_EXTENSION,
  194.               neval_args, 0,
  195.               eval_args, NULL);
  196. }
  197.  
  198. static void
  199. run (gchar      *name,
  200.      gint        nparams,
  201.      GimpParam  *param,
  202.      gint       *nreturn_vals,
  203.      GimpParam **return_vals)
  204. {
  205.   siod_output = stdout;
  206.  
  207.   /*  Determine before we allow scripts to register themselves
  208.    *   whether this is the base, automatically installed script-fu extension
  209.    */
  210.   if (strcmp (name, "extension_script_fu") == 0)
  211.     {
  212.       /*  Setup auxillary temporary procedures for the base extension  */
  213.       script_fu_auxillary_init ();
  214.  
  215.       script_fu_base = TRUE;
  216.     }
  217.   else
  218.     script_fu_base = FALSE;
  219.  
  220.   /*  Init the interpreter  */
  221.   init_interp ();
  222.  
  223.   /*  Load all of the available scripts  */
  224.   script_fu_find_scripts ();
  225.  
  226.   /*
  227.    *  The main, automatically installed script fu extension.
  228.    *  For things like logos and effects that are runnable from GIMP menus.
  229.    */
  230.   if (strcmp (name, "extension_script_fu") == 0)
  231.     {
  232.       static GimpParam  values[1];
  233.       GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  234.  
  235.       /*  Acknowledge that the extension is properly initialized  */
  236.       gimp_extension_ack ();
  237.  
  238.       while (TRUE)
  239.     gimp_extension_process (0);
  240.  
  241.       *nreturn_vals = 1;
  242.       *return_vals  = values;
  243.  
  244.       values[0].type          = GIMP_PDB_STATUS;
  245.       values[0].data.d_status = status;
  246.     }
  247.   /*
  248.    *  The script-fu console for interactive SIOD development
  249.    */
  250.   else if (strcmp (name, "extension_script_fu_console") == 0)
  251.     {
  252.       script_fu_console_run (name, nparams, param, nreturn_vals, return_vals);
  253.     }
  254. #ifndef G_OS_WIN32
  255.   /*
  256.    *  The script-fu server for remote operation
  257.    */
  258.   else if (strcmp (name, "extension_script_fu_server") == 0)
  259.     {
  260.       script_fu_server_run (name, nparams, param, nreturn_vals, return_vals);
  261.     }
  262. #endif
  263.   /*
  264.    *  A non-interactive "console" (for batch mode)
  265.    */
  266.   else if (strcmp (name, "extension_script_fu_eval") == 0)
  267.     {
  268.       script_fu_eval_run (name, nparams, param, nreturn_vals, return_vals);
  269.     }
  270. }
  271.  
  272. static gint
  273. init_interp (void)
  274. {
  275.   process_cla (sizeof (siod_argv) / sizeof (char *), siod_argv, 1);
  276.  
  277.   init_storage ();
  278.  
  279.   init_subrs ();
  280.   init_trace ();
  281.   init_regex ();
  282.   init_gimp  ();
  283.  
  284.   return 0;
  285. }
  286.  
  287. static void
  288. init_gimp (void)
  289. {
  290.   init_procedures ();
  291.   init_constants ();
  292. }
  293.  
  294. static void
  295. init_procedures (void)
  296. {
  297.   gchar          **proc_list;
  298.   gchar           *proc_name;
  299.   gchar           *arg_name;
  300.   gchar           *proc_blurb;
  301.   gchar           *proc_help;
  302.   gchar           *proc_author;
  303.   gchar           *proc_copyright;
  304.   gchar           *proc_date;
  305.   GimpPDBProcType  proc_type;
  306.   gint             nparams;
  307.   gint             nreturn_vals;
  308.   GimpParamDef    *params;
  309.   GimpParamDef    *return_vals;
  310.   gint             num_procs;
  311.   gint             i;
  312.  
  313.   /*  register the database execution procedure  */
  314.   init_lsubr ("gimp-proc-db-call",  marshall_proc_db_call);
  315.   init_lsubr ("script-fu-register", script_fu_register_call);
  316.   init_lsubr ("script-fu-quit",     script_fu_quit_call);
  317.  
  318.   gimp_procedural_db_query (".*", ".*", ".*", ".*", ".*", ".*", ".*", 
  319.                 &num_procs, &proc_list);
  320.  
  321.   /*  Register each procedure as a scheme func  */
  322.   for (i = 0; i < num_procs; i++)
  323.     {
  324.       proc_name = g_strdup (proc_list[i]);
  325.  
  326.       /*  lookup the procedure  */
  327.       if (gimp_procedural_db_proc_info (proc_name, 
  328.                     &proc_blurb, 
  329.                     &proc_help, 
  330.                     &proc_author,
  331.                     &proc_copyright, 
  332.                     &proc_date, 
  333.                     &proc_type, 
  334.                     &nparams, &nreturn_vals,
  335.                     ¶ms, &return_vals))
  336.     {
  337.       LISP args = NIL;
  338.       LISP code = NIL;
  339.       gint j;
  340.  
  341.       /*  convert the names to scheme-like naming conventions  */
  342.       convert_string (proc_name);
  343.  
  344.       /*  create a new scheme func that calls gimp-proc-db-call  */
  345.       for (j = 0; j < nparams; j++)
  346.         {
  347.           arg_name = g_strdup (params[j].name);
  348.           convert_string (arg_name);
  349.           args = cons (cintern (arg_name), args);
  350.           code = cons (cintern (arg_name), code);
  351.         }
  352.  
  353.       /*  reverse the list  */
  354.       args = nreverse (args);
  355.       code = nreverse (code);
  356.  
  357.       /*  set the scheme-based procedure name  */
  358.       args = cons (cintern (proc_name), args);
  359.  
  360.       /*  set the acture pdb procedure name  */
  361.       code = cons (cons (cintern ("quote"), 
  362.                  cons (cintern (proc_list[i]), NIL)), 
  363.                code);
  364.       code = cons (cintern ("gimp-proc-db-call"), code);
  365.  
  366.       leval_define (cons (args, cons (code, NIL)), NIL);
  367.  
  368.       /*  free the queried information  */
  369.       g_free (proc_blurb);
  370.       g_free (proc_help);
  371.       g_free (proc_author);
  372.       g_free (proc_copyright);
  373.       g_free (proc_date);
  374.       gimp_destroy_paramdefs (params, nparams);
  375.       gimp_destroy_paramdefs (return_vals, nreturn_vals);
  376.     }
  377.     }
  378.  
  379.   g_free (proc_list);
  380. }
  381.  
  382. static void
  383. init_constants (void)
  384. {
  385.   gchar *gimp_plugin_dir;
  386.  
  387.   setvar (cintern ("gimp-data-dir"), 
  388.       strcons (-1, gimp_data_directory ()), NIL);
  389.  
  390.   gimp_plugin_dir = gimp_gimprc_query ("gimp_plugin_dir");
  391.   if (gimp_plugin_dir)
  392.     {
  393.       setvar (cintern ("gimp-plugin-dir"), 
  394.           strcons (-1, gimp_plugin_dir), NIL);
  395.       g_free (gimp_plugin_dir);
  396.     }
  397.   
  398.   /* Generated constants */
  399.   init_generated_constants ();
  400.  
  401.   /* These are for backwards compatibility; they should be removed sometime */
  402.   setvar (cintern ("NORMAL"),         flocons (GIMP_NORMAL_MODE),       NIL);
  403.   setvar (cintern ("DISSOLVE"),       flocons (GIMP_DISSOLVE_MODE),     NIL);
  404.   setvar (cintern ("BEHIND"),         flocons (GIMP_BEHIND_MODE),       NIL);
  405.   setvar (cintern ("MULTIPLY"),       flocons (GIMP_MULTIPLY_MODE),     NIL);
  406.   setvar (cintern ("SCREEN"),         flocons (GIMP_SCREEN_MODE),       NIL);
  407.   setvar (cintern ("OVERLAY"),        flocons (GIMP_OVERLAY_MODE),      NIL);
  408.   setvar (cintern ("DIFFERENCE"),     flocons (GIMP_DIFFERENCE_MODE),   NIL);
  409.   setvar (cintern ("ADDITION"),       flocons (GIMP_ADDITION_MODE),     NIL);
  410.   setvar (cintern ("SUBTRACT"),       flocons (GIMP_SUBTRACT_MODE),     NIL);
  411.   setvar (cintern ("DARKEN-ONLY"),    flocons (GIMP_DARKEN_ONLY_MODE),  NIL);
  412.   setvar (cintern ("LIGHTEN-ONLY"),   flocons (GIMP_LIGHTEN_ONLY_MODE), NIL);
  413.   setvar (cintern ("HUE"),            flocons (GIMP_HUE_MODE),          NIL);
  414.   setvar (cintern ("SATURATION"),     flocons (GIMP_SATURATION_MODE),   NIL);
  415.   setvar (cintern ("COLOR"),          flocons (GIMP_COLOR_MODE),        NIL);
  416.   setvar (cintern ("VALUE"),          flocons (GIMP_VALUE_MODE),        NIL);
  417.   setvar (cintern ("DIVIDE"),         flocons (GIMP_DIVIDE_MODE),       NIL);
  418.  
  419.   setvar (cintern ("BLUR"),           flocons (GIMP_BLUR_CONVOLVE),     NIL);
  420.   setvar (cintern ("SHARPEN"),        flocons (GIMP_SHARPEN_CONVOLVE),  NIL);
  421.  
  422.   setvar (cintern ("RGB_IMAGE"),      flocons (GIMP_RGB_IMAGE),         NIL);
  423.   setvar (cintern ("RGBA_IMAGE"),     flocons (GIMP_RGBA_IMAGE),        NIL);
  424.   setvar (cintern ("GRAY_IMAGE"),     flocons (GIMP_GRAY_IMAGE),        NIL);
  425.   setvar (cintern ("GRAYA_IMAGE"),    flocons (GIMP_GRAYA_IMAGE),       NIL);
  426.   setvar (cintern ("INDEXED_IMAGE"),  flocons (GIMP_INDEXED_IMAGE),     NIL);
  427.   setvar (cintern ("INDEXEDA_IMAGE"), flocons (GIMP_INDEXEDA_IMAGE),    NIL);
  428.  
  429.   /* Useful misc stuff */
  430.   setvar (cintern ("TRUE"),           flocons (TRUE),  NIL);
  431.   setvar (cintern ("FALSE"),          flocons (FALSE), NIL);
  432.  
  433.   /*  Script-fu types  */
  434.   setvar (cintern ("SF-IMAGE"),       flocons (SF_IMAGE),      NIL);
  435.   setvar (cintern ("SF-DRAWABLE"),    flocons (SF_DRAWABLE),   NIL);
  436.   setvar (cintern ("SF-LAYER"),       flocons (SF_LAYER),      NIL);
  437.   setvar (cintern ("SF-CHANNEL"),     flocons (SF_CHANNEL),    NIL);
  438.   setvar (cintern ("SF-COLOR"),       flocons (SF_COLOR),      NIL);
  439.   setvar (cintern ("SF-TOGGLE"),      flocons (SF_TOGGLE),     NIL);
  440.   setvar (cintern ("SF-VALUE"),       flocons (SF_VALUE),      NIL);
  441.   setvar (cintern ("SF-STRING"),      flocons (SF_STRING),     NIL);
  442.   setvar (cintern ("SF-FILENAME"),    flocons (SF_FILENAME),   NIL);
  443.   setvar (cintern ("SF-ADJUSTMENT"),  flocons (SF_ADJUSTMENT), NIL);
  444.   setvar (cintern ("SF-FONT"),        flocons (SF_FONT),       NIL);
  445.   setvar (cintern ("SF-PATTERN"),     flocons (SF_PATTERN),    NIL);
  446.   setvar (cintern ("SF-BRUSH"),       flocons (SF_BRUSH),      NIL);
  447.   setvar (cintern ("SF-GRADIENT"),    flocons (SF_GRADIENT),   NIL);
  448.   setvar (cintern ("SF-OPTION"),      flocons (SF_OPTION),     NIL);
  449.  
  450.   /* for SF_ADJUSTMENT */
  451.   setvar (cintern ("SF-SLIDER"),      flocons (SF_SLIDER),     NIL);
  452.   setvar (cintern ("SF-SPINNER"),     flocons (SF_SPINNER),    NIL);
  453. }
  454.  
  455. static void
  456. convert_string (gchar *str)
  457. {
  458.   while (*str)
  459.     {
  460.       if (*str == '_') *str = '-';
  461.       str++;
  462.     }
  463. }
  464.  
  465. static gint
  466. sputs_fcn (gchar *st,
  467.        void  *dest)
  468. {
  469.   strcpy (*((gchar**)dest), st);
  470.   *((gchar**)dest) += strlen (st);
  471.  
  472.   return (1);
  473. }
  474.  
  475. static LISP
  476. lprin1s (LISP   exp,
  477.      gchar *dest)
  478. {
  479.   struct gen_printio s;
  480.  
  481.   s.putc_fcn    = NULL;
  482.   s.puts_fcn    = sputs_fcn;
  483.   s.cb_argument = &dest;
  484.  
  485.   lprin1g (exp, &s);
  486.  
  487.   return (NIL);
  488. }
  489.  
  490.  
  491. static LISP
  492. marshall_proc_db_call (LISP a)
  493. {
  494.   GimpParam       *args;
  495.   GimpParam       *values = NULL;
  496.   gint             nvalues;
  497.   gchar           *proc_name;
  498.   gchar           *proc_blurb;
  499.   gchar           *proc_help;
  500.   gchar           *proc_author;
  501.   gchar           *proc_copyright;
  502.   gchar           *proc_date;
  503.   GimpPDBProcType  proc_type;
  504.   gint             nparams;
  505.   gint             nreturn_vals;
  506.   GimpParamDef    *params;
  507.   GimpParamDef    *return_vals;
  508.   gchar  error_str[256];
  509.   gint   i;
  510.   gint   success = TRUE;
  511.   LISP   color_list;
  512.   LISP   intermediate_val;
  513.   LISP   return_val = NIL;
  514.   gchar *string;
  515.   gint   string_len;
  516.   LISP   a_saved;
  517.  
  518.   /* Save a in case it is needed for an error message. */
  519.   a_saved = a;
  520.  
  521.   /*  Make sure there are arguments  */
  522.   if (a == NIL)
  523.     return my_err ("Procedure database argument marshaller was called with no arguments. "
  524.            "The procedure to be executed and the arguments it requires "
  525.            "(possibly none) must be specified.", NIL);
  526.  
  527.   /*  Derive the pdb procedure name from the argument 
  528.       or first argument of a list  */
  529.   if (TYPEP (a, tc_cons))
  530.     proc_name = get_c_string (car (a));
  531.   else
  532.     proc_name = get_c_string (a);
  533.  
  534.   /*  report the current command  */
  535.   script_fu_report_cc (proc_name);
  536.  
  537.   /*  Attempt to fetch the procedure from the database  */
  538.   if (! gimp_procedural_db_proc_info (proc_name, 
  539.                       &proc_blurb, 
  540.                       &proc_help, 
  541.                       &proc_author,
  542.                       &proc_copyright,
  543.                       &proc_date,
  544.                       &proc_type,
  545.                       &nparams, &nreturn_vals,
  546.                       ¶ms, &return_vals))
  547.     return my_err ("Invalid procedure name specified.", NIL);
  548.  
  549.  
  550.   /*  Free unused query information.  */
  551.  
  552.   g_free (proc_blurb);
  553.   g_free (proc_help);
  554.   g_free (proc_author);
  555.   g_free (proc_copyright);
  556.   g_free (proc_date);
  557.  
  558.   for (i = 0; i < nparams; i++)
  559.     {
  560.       g_free (params[i].name);
  561.       g_free (params[i].description);
  562.     }
  563.  
  564.   for (i = 0; i < nreturn_vals; i++)
  565.     {
  566.       g_free (return_vals[i].name);
  567.       g_free (return_vals[i].description);
  568.     }
  569.  
  570.  
  571.   /*  Check the supplied number of arguments  */
  572.   if ((nlength (a) - 1) != nparams)
  573.     {
  574.       g_snprintf (error_str, sizeof (error_str), 
  575.           "Invalid arguments supplied to %s--(# args: %ld, expecting: %d)",
  576.           proc_name, (nlength (a) - 1), nparams);
  577.       return my_err (error_str, NIL);
  578.     }
  579.  
  580.   /*  Marshall the supplied arguments  */
  581.   if (nparams)
  582.     args = g_new (GimpParam, nparams);
  583.   else
  584.     args = NULL;
  585.  
  586.   a = cdr (a);
  587.   for (i = 0; i < nparams; i++)
  588.     {
  589.       switch (params[i].type)
  590.     {
  591.     case GIMP_PDB_INT32:
  592.       if (!TYPEP (car (a), tc_flonum))
  593.         success = FALSE;
  594.       if (success)
  595.         {
  596.           args[i].type = GIMP_PDB_INT32;
  597.           args[i].data.d_int32 = get_c_long (car (a));
  598.         }
  599.       break;
  600.  
  601.     case GIMP_PDB_INT16:
  602.       if (!TYPEP (car (a), tc_flonum))
  603.         success = FALSE;
  604.       if (success)
  605.         {
  606.           args[i].type = GIMP_PDB_INT16;
  607.           args[i].data.d_int16 = (gint16) get_c_long (car (a));
  608.         }
  609.       break;
  610.  
  611.     case GIMP_PDB_INT8:
  612.       if (!TYPEP (car (a), tc_flonum))
  613.         success = FALSE;
  614.       if (success)
  615.         {
  616.           args[i].type = GIMP_PDB_INT8;
  617.           args[i].data.d_int8 = (gint8) get_c_long (car (a));
  618.         }
  619.       break;
  620.  
  621.     case GIMP_PDB_FLOAT:
  622.       if (!TYPEP (car (a), tc_flonum))
  623.         success = FALSE;
  624.       if (success)
  625.         {
  626.           args[i].type = GIMP_PDB_FLOAT;
  627.           args[i].data.d_float = get_c_double (car (a));
  628.         }
  629.       break;
  630.  
  631.     case GIMP_PDB_STRING:
  632.       if (!TYPEP (car (a), tc_string))
  633.         success = FALSE;
  634.       if (success)
  635.         {
  636.           args[i].type = GIMP_PDB_STRING;
  637.           args[i].data.d_string = get_c_string (car (a));
  638.         }
  639.       break;
  640.  
  641.     case GIMP_PDB_INT32ARRAY:
  642.       if (!TYPEP (car (a), tc_long_array))
  643.         success = FALSE;
  644.       if (success)
  645.         {
  646.           args[i].type = GIMP_PDB_INT32ARRAY;
  647.           args[i].data.d_int32array = 
  648.         (gint32*) (car (a))->storage_as.long_array.data;
  649.         }
  650.       break;
  651.  
  652.     case GIMP_PDB_INT16ARRAY:
  653.       if (!TYPEP (car (a), tc_long_array))
  654.         success = FALSE;
  655.       if (success)
  656.         {
  657.           args[i].type = GIMP_PDB_INT16ARRAY;
  658.           args[i].data.d_int16array = 
  659.         (gint16*) (car (a))->storage_as.long_array.data;
  660.         }
  661.       break;
  662.  
  663.     case GIMP_PDB_INT8ARRAY:
  664.       if (!TYPEP (car (a), tc_byte_array))
  665.         success = FALSE;
  666.       if (success)
  667.         {
  668.           args[i].type = GIMP_PDB_INT8ARRAY;
  669.           args[i].data.d_int8array = 
  670.         (gint8*) (car (a))->storage_as.string.data;
  671.         }
  672.       break;
  673.  
  674.     case GIMP_PDB_FLOATARRAY:
  675.       if (!TYPEP (car (a), tc_double_array))
  676.         success = FALSE;
  677.       if (success)
  678.         {
  679.           args[i].type = GIMP_PDB_FLOATARRAY;
  680.           args[i].data.d_floatarray = (car (a))->storage_as.double_array.data;
  681.         }
  682.       break;
  683.  
  684.     case GIMP_PDB_STRINGARRAY:
  685.       if (!TYPEP (car (a), tc_cons))
  686.         success = FALSE;
  687.       if (success)
  688.         {
  689.           args[i].type = GIMP_PDB_STRINGARRAY;
  690.  
  691.           /*  Set the array  */
  692.           {
  693.         gint j;
  694.         gint num_strings;
  695.         gchar **array;
  696.         LISP list;
  697.  
  698.         list = car (a);
  699.         num_strings = args[i - 1].data.d_int32;
  700.         if (nlength (list) != num_strings)
  701.           return my_err ("String array argument has incorrectly specified length", NIL);
  702.         array = args[i].data.d_stringarray = 
  703.           g_new (char *, num_strings);
  704.  
  705.         for (j = 0; j < num_strings; j++)
  706.           {
  707.             array[j] = get_c_string (car (list));
  708.             list = cdr (list);
  709.           }
  710.           }
  711.         }
  712.       break;
  713.  
  714.     case GIMP_PDB_COLOR:
  715.       if (!TYPEP (car (a), tc_cons))
  716.         success = FALSE;
  717.       if (success)
  718.         {
  719.           args[i].type = GIMP_PDB_COLOR;
  720.           color_list = car (a);
  721.           args[i].data.d_color.red = get_c_long (car (color_list));
  722.           color_list = cdr (color_list);
  723.           args[i].data.d_color.green = get_c_long (car (color_list));
  724.           color_list = cdr (color_list);
  725.           args[i].data.d_color.blue = get_c_long (car (color_list));
  726.         }
  727.       break;
  728.  
  729.     case GIMP_PDB_REGION:
  730.       return my_err ("Regions are currently unsupported as arguments", 
  731.              car (a));
  732.       break;
  733.  
  734.     case GIMP_PDB_DISPLAY:
  735.       if (!TYPEP (car (a), tc_flonum))
  736.         success = FALSE;
  737.       if (success)
  738.         {
  739.           args[i].type = GIMP_PDB_DISPLAY;
  740.           args[i].data.d_int32 = get_c_long (car (a));
  741.         }
  742.       break;
  743.  
  744.     case GIMP_PDB_IMAGE:
  745.       if (!TYPEP (car (a), tc_flonum))
  746.         success = FALSE;
  747.       if (success)
  748.         {
  749.           args[i].type = GIMP_PDB_IMAGE;
  750.           args[i].data.d_int32 = get_c_long (car (a));
  751.         }
  752.       break;
  753.  
  754.     case GIMP_PDB_LAYER:
  755.       if (!TYPEP (car (a), tc_flonum))
  756.         success = FALSE;
  757.       if (success)
  758.         {
  759.           args[i].type = GIMP_PDB_LAYER;
  760.           args[i].data.d_int32 = get_c_long (car (a));
  761.         }
  762.       break;
  763.  
  764.     case GIMP_PDB_CHANNEL:
  765.       if (!TYPEP (car (a), tc_flonum))
  766.         success = FALSE;
  767.       if (success)
  768.         {
  769.           args[i].type = GIMP_PDB_CHANNEL;
  770.           args[i].data.d_int32 = get_c_long (car (a));
  771.         }
  772.       break;
  773.  
  774.     case GIMP_PDB_DRAWABLE:
  775.       if (!TYPEP (car (a), tc_flonum))
  776.         success = FALSE;
  777.       if (success)
  778.         {
  779.           args[i].type = GIMP_PDB_DRAWABLE;
  780.           args[i].data.d_int32 = get_c_long (car (a));
  781.         }
  782.       break;
  783.  
  784.     case GIMP_PDB_SELECTION:
  785.       if (!TYPEP (car (a), tc_flonum))
  786.         success = FALSE;
  787.       if (success)
  788.         {
  789.           args[i].type = GIMP_PDB_SELECTION;
  790.           args[i].data.d_int32 = get_c_long (car (a));
  791.         }
  792.       break;
  793.  
  794.     case GIMP_PDB_BOUNDARY:
  795.       return my_err ("Boundaries are currently unsupported as arguments", 
  796.              car (a));
  797.       break;
  798.  
  799.     case GIMP_PDB_PATH:
  800.       return my_err ("Paths are currently unsupported as arguments", 
  801.              car (a));
  802.       break;
  803.  
  804.     case GIMP_PDB_PARASITE:
  805.       if (!TYPEP (car (a), tc_cons))
  806.         success = FALSE;
  807.       if (success)
  808.         {
  809.           args[i].type = GIMP_PDB_PARASITE;
  810.           /* parasite->name */
  811.           intermediate_val = car (a);
  812.           args[i].data.d_parasite.name = 
  813.         get_c_string (car (intermediate_val));
  814.           
  815.           /* parasite->flags */
  816.           intermediate_val = cdr (intermediate_val);
  817.           args[i].data.d_parasite.flags = get_c_long (car(intermediate_val));
  818.  
  819.           /* parasite->size */
  820.           intermediate_val = cdr (intermediate_val);
  821.           args[i].data.d_parasite.size =
  822.         (car (intermediate_val))->storage_as.string.dim;
  823.  
  824.           /* parasite->data */
  825.           args[i].data.d_parasite.data =
  826.         (void*) (car (intermediate_val))->storage_as.string.data;
  827.         }
  828.       break;
  829.  
  830.     case GIMP_PDB_STATUS:
  831.       return my_err ("Status is for return types, not arguments", car (a));
  832.       break;
  833.  
  834.     default:
  835.       return my_err ("Unknown argument type", NIL);
  836.     }
  837.  
  838.       a = cdr (a);
  839.     }
  840.  
  841.   if (success)
  842.     values = gimp_run_procedure2 (proc_name, &nvalues, nparams, args);
  843.   else
  844.     return my_err ("Invalid types specified for arguments", NIL);
  845.  
  846.   /*  Check the return status  */
  847.   if (! values)
  848.     {
  849.       strcpy (error_str, "Procedural database execution did not return a status:\n    ");
  850.       lprin1s (a_saved, error_str + strlen(error_str));
  851.       
  852.       return my_err (error_str, NIL);
  853.     }
  854.  
  855.   switch (values[0].data.d_status)
  856.     {
  857.     case GIMP_PDB_EXECUTION_ERROR:
  858.       strcpy (error_str, "Procedural database execution failed:\n    ");
  859.       lprin1s (a_saved, error_str + strlen(error_str));
  860.       return my_err (error_str, NIL);
  861.       break;
  862.  
  863.     case GIMP_PDB_CALLING_ERROR:
  864.       strcpy (error_str, "Procedural database execution failed on invalid input arguments:\n    ");
  865.       lprin1s (a_saved, error_str + strlen(error_str));
  866.       return my_err (error_str, NIL);
  867.       break;
  868.  
  869.     case GIMP_PDB_SUCCESS:
  870.       return_val = NIL;
  871.  
  872.       for (i = 0; i < nvalues - 1; i++)
  873.     {
  874.       switch (return_vals[i].type)
  875.         {
  876.         case GIMP_PDB_INT32:
  877.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  878.                  return_val);
  879.           break;
  880.  
  881.         case GIMP_PDB_INT16:
  882.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  883.                  return_val);
  884.           break;
  885.  
  886.         case GIMP_PDB_INT8:
  887.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  888.                  return_val);
  889.           break;
  890.  
  891.         case GIMP_PDB_FLOAT:
  892.           return_val = cons (flocons (values[i + 1].data.d_float), 
  893.                  return_val);
  894.           break;
  895.  
  896.         case GIMP_PDB_STRING:
  897.           string = (gchar *) values[i + 1].data.d_string;
  898.           string_len = strlen (string);
  899.           return_val = cons (strcons (string_len, string), return_val);
  900.           break;
  901.  
  902.         case GIMP_PDB_INT32ARRAY:
  903.           {
  904.         LISP array;
  905.         int j;
  906.  
  907.         array = arcons (tc_long_array, values[i].data.d_int32, 0);
  908.         for (j = 0; j < values[i].data.d_int32; j++)
  909.           {
  910.             array->storage_as.long_array.data[j] = 
  911.               values[i + 1].data.d_int32array[j];
  912.           }
  913.         return_val = cons (array, return_val);
  914.           }
  915.           break;
  916.  
  917.         case GIMP_PDB_INT16ARRAY:
  918.           return my_err ("Arrays are currently unsupported as return values", NIL);
  919.           break;
  920.  
  921.         case GIMP_PDB_INT8ARRAY:
  922.           {
  923.         LISP array;
  924.         int j;
  925.  
  926.         array = arcons (tc_byte_array, values[i].data.d_int32, 0);
  927.         for (j = 0; j < values[i].data.d_int32; j++)
  928.           {
  929.             array->storage_as.string.data[j] = 
  930.               values[i + 1].data.d_int8array[j];
  931.           }
  932.         return_val = cons (array, return_val);
  933.           }
  934.           break;
  935.  
  936.         case GIMP_PDB_FLOATARRAY:
  937.           {
  938.         LISP array;
  939.         int j;
  940.  
  941.         array = arcons (tc_double_array, values[i].data.d_int32, 0);
  942.         for (j = 0; j < values[i].data.d_int32; j++)
  943.           {
  944.             array->storage_as.double_array.data[j] = 
  945.               values[i + 1].data.d_floatarray[j];
  946.           }
  947.         return_val = cons (array, return_val);
  948.           }
  949.           break;
  950.  
  951.         case GIMP_PDB_STRINGARRAY:
  952.           /*  string arrays are always implemented such that the previous
  953.            *  return value contains the number of strings in the array
  954.            */
  955.           {
  956.         int j;
  957.         int num_strings = values[i].data.d_int32;
  958.         LISP string_array = NIL;
  959.         char **array = (char **) values[i + 1].data.d_stringarray;
  960.  
  961.         for (j = 0; j < num_strings; j++)
  962.           {
  963.             string_len = strlen (array[j]);
  964.             string_array = cons (strcons (string_len, array[j]), 
  965.                      string_array);
  966.           }
  967.  
  968.         return_val = cons (nreverse (string_array), return_val);
  969.           }
  970.           break;
  971.  
  972.         case GIMP_PDB_COLOR:
  973.           intermediate_val = cons (flocons ((int) values[i + 1].data.d_color.red),
  974.                        cons (flocons ((int) values[i + 1].data.d_color.green),
  975.                          cons (flocons ((int) values[i + 1].data.d_color.blue),
  976.                            NIL)));
  977.           return_val = cons (intermediate_val, return_val);
  978.           break;
  979.  
  980.         case GIMP_PDB_REGION:
  981.           return my_err ("Regions are currently unsupported as return values", NIL);
  982.           break;
  983.  
  984.         case GIMP_PDB_DISPLAY:
  985.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  986.                  return_val);
  987.           break;
  988.  
  989.         case GIMP_PDB_IMAGE:
  990.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  991.                  return_val);
  992.           break;
  993.  
  994.         case GIMP_PDB_LAYER:
  995.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  996.                  return_val);
  997.           break;
  998.  
  999.         case GIMP_PDB_CHANNEL:
  1000.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  1001.                  return_val);
  1002.           break;
  1003.  
  1004.         case GIMP_PDB_DRAWABLE:
  1005.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  1006.                  return_val);
  1007.           break;
  1008.  
  1009.         case GIMP_PDB_SELECTION:
  1010.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  1011.                  return_val);
  1012.           break;
  1013.  
  1014.         case GIMP_PDB_BOUNDARY:
  1015.           return my_err ("Boundaries are currently unsupported as return values", NIL);
  1016.           break;
  1017.  
  1018.         case GIMP_PDB_PATH:
  1019.           return my_err ("Paths are currently unsupported as return values", NIL);
  1020.           break;
  1021.  
  1022.         case GIMP_PDB_PARASITE:
  1023.           {
  1024.         LISP name, flags, data;
  1025.  
  1026.         if (values[i + 1].data.d_parasite.name == NULL)
  1027.           {
  1028.             return_val = my_err("Error: null parasite", NIL);
  1029.           }
  1030.         else
  1031.           {
  1032.             string_len = strlen (values[i + 1].data.d_parasite.name);
  1033.             name    = strcons (string_len,
  1034.                        values[i + 1].data.d_parasite.name);
  1035.             
  1036.             flags   = flocons (values[i + 1].data.d_parasite.flags);
  1037.             data    = arcons (tc_byte_array,
  1038.                       values[i+1].data.d_parasite.size, 0);
  1039.             memcpy(data->storage_as.string.data,
  1040.                values[i+1].data.d_parasite.data, 
  1041.                values[i+1].data.d_parasite.size); 
  1042.             
  1043.             intermediate_val = cons (name, 
  1044.                          cons(flags, cons(data, NIL)));
  1045.             return_val = cons (intermediate_val, return_val);
  1046.           }
  1047.           }
  1048.           break;
  1049.  
  1050.         case GIMP_PDB_STATUS:
  1051.           return my_err ("Procedural database execution returned multiple status values", NIL);
  1052.           break;
  1053.  
  1054.         default:
  1055.           return my_err ("Unknown return type", NIL);
  1056.         }
  1057.     }
  1058.       break;
  1059.  
  1060.     case GIMP_PDB_PASS_THROUGH:
  1061.     case GIMP_PDB_CANCEL:   /*  should we do something here?  */
  1062.       break;
  1063.     }
  1064.  
  1065.   /*  free up the executed procedure return values  */
  1066.   gimp_destroy_params (values, nvalues);
  1067.  
  1068.   /*  free up arguments and values  */
  1069.   g_free (args);
  1070.  
  1071.   g_free (params);
  1072.   g_free (return_vals);
  1073.  
  1074.   /*  reverse the return values  */
  1075.   return_val = nreverse (return_val);
  1076. #ifndef G_OS_WIN32
  1077.   /*  if we're in server mode, listen for additional commands for 10 ms  */
  1078.   if (server_mode)
  1079.     script_fu_server_listen (10);
  1080. #endif
  1081.  
  1082. #ifdef GDK_WINDOWING_WIN32
  1083.   /* This seems to help a lot on Windoze. */
  1084.   while (gtk_events_pending ())
  1085.     gtk_main_iteration ();
  1086. #endif
  1087.  
  1088.   return return_val;
  1089. }
  1090.  
  1091. static LISP
  1092. script_fu_register_call (LISP a)
  1093. {
  1094.   if (script_fu_base)
  1095.     return script_fu_add_script (a);
  1096.   else
  1097.     return NIL;
  1098. }
  1099.  
  1100. static LISP
  1101. script_fu_quit_call (LISP a)
  1102. {
  1103.   script_fu_done = TRUE;
  1104.  
  1105.   return NIL;
  1106. }
  1107.  
  1108. static void
  1109. script_fu_auxillary_init (void)
  1110. {
  1111.   static GimpParamDef args[] =
  1112.   {
  1113.     { GIMP_PDB_INT32, "run_mode", "[Interactive], non-interactive" }
  1114.   };
  1115.   static gint nargs = sizeof (args) / sizeof (args[0]);
  1116.  
  1117.   INIT_I18N_UI();
  1118.  
  1119.   gimp_install_temp_proc ("script_fu_refresh",
  1120.               _("Re-read all available scripts"),
  1121.               _("Re-read all available scripts"),
  1122.               "Spencer Kimball & Peter Mattis",
  1123.               "Spencer Kimball & Peter Mattis",
  1124.               "1997",
  1125.               N_("<Toolbox>/Xtns/Script-Fu/Refresh"),
  1126.               NULL,
  1127.               GIMP_TEMPORARY,
  1128.               nargs, 0,
  1129.               args, NULL,
  1130.               script_fu_refresh_proc);
  1131. }
  1132.  
  1133. static void
  1134. script_fu_refresh_proc (gchar       *name,
  1135.             gint         nparams,
  1136.             GimpParam   *params,
  1137.             gint        *nreturn_vals,
  1138.             GimpParam  **return_vals)
  1139. {
  1140.   static GimpParam  values[1];
  1141.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  1142.  
  1143.   /*  Reload all of the available scripts  */
  1144.   script_fu_find_scripts ();
  1145.  
  1146.   *nreturn_vals = 1;
  1147.   *return_vals  = values;
  1148.  
  1149.   values[0].type          = GIMP_PDB_STATUS;
  1150.   values[0].data.d_status = status;
  1151. }
  1152.